#pragma once

#include <opencv2/opencv.hpp>
#include "opencv2/imgcodecs/legacy/constants_c.h"
#include "opencv2/imgproc/types_c.h"

#include "utils.h"
#include "acl/acl.h"
#include "dimp/model_process.h"
#include "dimp/preprocess_for_init.hpp"
#include "dimp/dimp_init.hpp"
#include <memory>
#include <vector>

#define NORMAL 0
#define NOT_FOUND 1
#define UNCERTAIN 2
#define HARD_NEGATIVE 3

using namespace std;
using namespace cv;

class Optimizer {
    public:
    Optimizer(const char* model_01_path, const char* model_02_path);
    ~Optimizer();

    Result Init(int32_t& deviceId, aclrtContext& context, aclrtStream& stream, aclrtRunMode& runMode);

    Result LoadInputDataForInitialOptimizer(Nodes classifier_feats, Nodes init_weight,  vector<Target_Box> transform_boxes);
    // Result LoadInputDataForTrackingOptimizer(void* classifier_feats, vector<Target_Box> transform_boxes, void* init_weight);
    Result LoadInputDataForTrackingOptimizer(Nodes classifier_feats, void* origin_weight, int train_nums, int frame_nums, int now_state, Vector now_pos, Vector now_size);

    Result InferenceForInitialOptimizer();
    Result InferenceForTrackingOptimizer(bool update_flag, bool get_result);

    Result CreateInputdDataset_for_InitialOptimizer();

    Result CreateInputdDataset_for_TrackingOptimizer();

    void DestroyResource();

    // Result CreateInputdDataset_for_TrackingOptimizer();

    Nodes final_weights_;
    Nodes new_weights_;

    private:
     //Initializes the ACL resource
    Result InitResource();
    //Loading reasoning model
    Result InitModel();

    void* GetInferenceOutputItem(uint32_t& itemDataSize,
    aclmdlDataset* inferenceOutput,
    uint32_t idx);

    private:
    int32_t deviceId_;
    aclrtContext context_;
    aclrtStream stream_;
    aclrtStream update_stream_;
    ModelDimpProcess initial_optimizer_;
    ModelDimpProcess tracking_optimizer_;

    const char* initial_optimizer_path_;
    const char* tracking_optimizer_path_;


    vector<cv::Mat> sample_img_;
    void* classifier_feats_DataBuf_;
    void* init_weight_DataBuf_;
    void* bboxesBuf_;
    float bboxes_[13][4];
    uint32_t bboxesSize_;

    void* origin_weight_DataBuf_;
    void* tracking_bboxes_Buf_;
    float tracking_bboxes_[50][4];
    uint32_t tracking_bboxesSize_;
    void* tracking_bboxesBuf_;
    float sample_weight_[50];
    uint32_t sample_weightSize_;
    void* sample_weightBuf_;
    void* tracking_classifier_feats_DataBuf_;
    int prev_ind_;
   
    aclrtRunMode runMode_;   //Run mode, which is whether the current application is running on atlas200DK or AI1

    bool isInited_;     //Initializes the tag to prevent inference instances from being initialized multiple times




};